package com.totem.admin.schedule;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.totem.admin.model.TSubscribeDailyEnd;
import com.totem.admin.vo.ReturnAwardVO;
import com.totem.base.constants.CommonConstants;
import com.totem.base.enums.*;
import com.totem.customer.mapper.TCustomerMapper;
import com.totem.customer.mapper.TInviteMapper;
import com.totem.customer.mapper.TMemberMapper;
import com.totem.customer.model.TCustomers;
import com.totem.customer.model.TInvite;
import com.totem.customer.model.TMembers;
import com.totem.customer.serivce.ITMemberService;
import com.totem.customer.vo.SubscribeIncentiveVO;
import com.totem.customer.vo.TeamIncentiveVO;
import com.totem.order.mapper.TOrderMapper;
import com.totem.order.mapper.TSubscribeOrderItemMapper;
import com.totem.order.mapper.TWalletJournalMapper;
import com.totem.order.mapper.TWalletMapper;
import com.totem.order.model.TOrders;
import com.totem.order.model.TSubscribeOrderItems;
import com.totem.order.model.TWalletJournal;
import com.totem.order.model.TWallets;
import com.totem.order.service.ITWalletJournalService;
import com.totem.order.service.ITWalletService;
import com.totem.product.mapper.TSubscribeMapper;
import com.totem.product.model.TSubscribe;
import com.totem.startup.InitialGlobalConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Component
public class SubscribeAwardTask {
    //@Autowired
    //private IMemberCommonService iMemberCommonService;
    @Autowired
    private TCustomerMapper tCustomerMapper;
    @Autowired
    private TOrderMapper tOrderMapper;
    @Autowired
    private TWalletMapper tWalletMapper;
    @Autowired
    private TInviteMapper tInviteMapper;
    @Autowired
    private TMemberMapper tMemberMapper;
    @Autowired
    private TWalletJournalMapper tWalletJournalMapper;
    @Autowired
    private TSubscribeMapper tSubscribeMapper;
    @Autowired
    private TSubscribeOrderItemMapper tSubscribeOrderItemMapper;
    @Autowired
    private ITWalletService itWalletService;
    @Autowired
    private ITWalletJournalService itWalletJournalService;
    @Autowired
    private ITMemberService itMemberService;

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void subscribeReturnAward(List<TSubscribeDailyEnd> subscribeDailyEndList){
        if(CollectionUtils.isEmpty(subscribeDailyEndList)){
            return;
        }

        Map<Long, BigDecimal> customerReturnMap = new HashMap<>();
        subscribeDailyEndList.forEach(sde->{
            Long customerId = sde.getCustomerId();
            BigDecimal returnAmt = customerReturnMap.computeIfAbsent(customerId, k -> BigDecimal.ZERO);
            customerReturnMap.put(customerId, returnAmt.add(sde.getEarnings()));
        });

        List<Long> normalCustomerIdList = subscribeDailyEndList.stream().map(TSubscribeDailyEnd::getCustomerId).toList();
        LambdaQueryWrapper<TInvite> inviteQuery = new LambdaQueryWrapper<>();
        inviteQuery.in(TInvite::getInviteeId, normalCustomerIdList);
        List<TInvite> inviteList = tInviteMapper.selectList(inviteQuery);
        if(CollectionUtils.isEmpty(inviteList)){
            log.warn("无邀请人可给予奖励");
            return;
        }

        Map<Long, List<Long>> invitePathMap = inviteList.stream()
                .collect(Collectors.toMap(
                        TInvite::getInviteeId,
                        v-> Arrays.stream(v.getPath().split(",")).map(Long::valueOf).toList()));

        customerReturnMap.forEach((customerId, earnings) -> {
            List<Long> walkInviterIds = invitePathMap.get(customerId);
            // customerId是正常的,其父级必然也都是正常的
            if (!CollectionUtils.isEmpty(walkInviterIds)) {
                // 计算收益奖励,包括推荐和团队激励(不包括特殊认购的日收益)
                Long directParentId = walkInviterIds.get(0);
                // 产生的收益都是USDO
                String currency = CurrencyEnum.USDO.getCode();

                Map<Integer, BigDecimal> inviteAwardRule = InitialGlobalConfig.INVITE_AWARD_RULE;
                Map<Integer, TeamIncentiveVO> teamMotivation = InitialGlobalConfig.TEAM_MOTIVATION_RULE;

                LambdaQueryWrapper<TMembers> memberQuery = new LambdaQueryWrapper<>();
                memberQuery.in(TMembers::getCustomerId, walkInviterIds);
                List<TMembers> memberList = tMemberMapper.selectList(memberQuery);
                Map<Long, TMembers> membersMap = memberList.stream().collect(Collectors.toMap(TMembers::getCustomerId, Function.identity()));

                TMembers currentMember = tMemberMapper.selectById(customerId);

                // 计算邀请奖励
                Map<Long, ReturnAwardVO> inviteAward = new HashMap<>();
                // 邀请奖励最高到10代,因此父级也最多查到10代
                for(int i=0; i<inviteAwardRule.size() && i<walkInviterIds.size(); i++){
                    Long parentId = walkInviterIds.get(i);
                    BigDecimal awardAmt = inviteAwardRule.get(i).multiply(earnings).setScale(CommonConstants.DEFAULT_RETURN_AWARD_SCALE, RoundingMode.HALF_UP);
                    ReturnAwardVO vo = new ReturnAwardVO();
                    vo.setReturnAmt(earnings);
                    vo.setReturnAwardAmt(awardAmt);
                    vo.setRate(inviteAwardRule.get(i));
                    inviteAward.put(parentId, vo);
                }

                // 计算团队奖励
                int currentLevel = currentMember.getEnjoyLevel();
                Map<Long, ReturnAwardVO> teamAward = new HashMap<>();
                // 当前客户(购买认购包)的等级也要计入团队奖励的计算中
                int maxLevel = currentLevel;
                BigDecimal awardRetrunRate = new BigDecimal("0.2");
                // @Deprecated 当父级客户与认购客户级别一致时,只有第一次拿认购收益的20%,后面都拿奖励的20%
                // 20240408 平级只拿一次20%,后续都不拿了,中间等级较低的不拿,后面平级的拿(必须满足仅一次)
                boolean hasSame = false;
                ReturnAwardVO maxLevelReturnAwardVO = new ReturnAwardVO();
                maxLevelReturnAwardVO.setRate(BigDecimal.ZERO);
                maxLevelReturnAwardVO.setReturnAmt(BigDecimal.ZERO);
                maxLevelReturnAwardVO.setReturnAwardAmt(BigDecimal.ZERO);
                for(int i=0; i<walkInviterIds.size(); i++){
                    // @Deprecated 上一个邀请人的会员等级已经达到最大,奖励已发完
                    // @Deprecated 20240404 需求补充:同级时,则拿第一个同级的奖励的20%,即到最高级时,后续有同级的,也能继续拿到收益.因此不再直接break
                    // 20240408 需求调整:父级路径上同级20%的奖励只拿一次
                    if(maxLevel>teamMotivation.size()){
                        break;
                    }
                    Long parentId = walkInviterIds.get(i);
                    TMembers tMembers = membersMap.get(parentId);
                    // 计算奖励时以待遇等级为准
                    int parentLevel = tMembers.getEnjoyLevel();
                    if(parentLevel==0){
                        continue;
                    }
                    // @Deprecated 子树中会员的最大等级不比当前会员的低,则当前会员无法再分到奖励
                    // 20240329, 遗漏需求补完: 当前会员与子树最大等级同级时,原来是不再获取奖励,实际应该是获得收益的奖励的20%, 待确认
                    // 子树中会员的最大等级比当前会员高,则当前会员无法再分到奖励
                    if(maxLevel>parentLevel){
                        continue;
                    }
                    // 子树中会员的最大等级与当前会员一样,则当前会员将得到最大等级会员所得奖励的20%,仅一次
                    if(maxLevel==parentLevel){
                        if(maxLevel==currentLevel) {
                            if(!hasSame) {
                                maxLevelReturnAwardVO = new ReturnAwardVO();
                                BigDecimal awardRetrunAwardAmt = earnings.multiply(awardRetrunRate).setScale(CommonConstants.DEFAULT_RETURN_AWARD_SCALE, RoundingMode.HALF_UP);
                                maxLevelReturnAwardVO.setReturnAmt(earnings);
                                maxLevelReturnAwardVO.setReturnAwardAmt(awardRetrunAwardAmt);
                                maxLevelReturnAwardVO.setRate(awardRetrunRate);
                                teamAward.put(parentId, maxLevelReturnAwardVO);
                                hasSame=true;
                            }
                        }else {
                            // 延用子树中最大等级的最低层的收益金额进行计算,直到遇到更高级的父级
                            if(!hasSame) {
                                BigDecimal awardReturnAmt = maxLevelReturnAwardVO.getReturnAmt();
                                if (awardReturnAmt.compareTo(BigDecimal.ZERO) > 0) {
                                    maxLevelReturnAwardVO = new ReturnAwardVO();
                                    BigDecimal awardRetrunAwardAmt = awardReturnAmt.multiply(awardRetrunRate).setScale(CommonConstants.DEFAULT_RETURN_AWARD_SCALE, RoundingMode.HALF_UP);
                                    maxLevelReturnAwardVO.setReturnAmt(awardReturnAmt);
                                    maxLevelReturnAwardVO.setReturnAwardAmt(awardRetrunAwardAmt);
                                    maxLevelReturnAwardVO.setRate(awardRetrunRate);
                                    teamAward.put(parentId, maxLevelReturnAwardVO);
                                    hasSame=true;
                                }
                            }
                        }
                        continue;
                    }
                    // 当前会员的等级大于子树中会员的最大等级,还有奖励可分
                    TeamIncentiveVO parentTeamIncentive = teamMotivation.get(parentLevel);
                    BigDecimal distributive = parentTeamIncentive.getIncome();
                    // 计算可分配收益率(级差),此时parentLevel>maxLevel
                    if (maxLevel > 0) {
                        TeamIncentiveVO maxTeamIncentive = teamMotivation.get(maxLevel);
                        distributive = distributive.subtract(maxTeamIncentive.getIncome());
                    }
                    // 可分配收益率计算完, 更新当前会员树的最大会员等级
                    maxLevel = parentLevel;
                    // 计算奖金=可分配收益率*当前客户认购包收益
                    BigDecimal awardAmt = distributive.multiply(earnings).setScale(CommonConstants.DEFAULT_RETURN_AWARD_SCALE, RoundingMode.HALF_UP);
                    ReturnAwardVO vo = new ReturnAwardVO();
                    vo.setReturnAmt(earnings);
                    vo.setReturnAwardAmt(awardAmt);
                    vo.setRate(distributive);
                    teamAward.put(parentId, vo);

                    // 遇到更高级的父级,就使用该父级的奖励金额作为同级收益的基数
                    maxLevelReturnAwardVO = new ReturnAwardVO();
                    maxLevelReturnAwardVO.setReturnAmt(awardAmt);
                    // 更高等级的客户,其父级还没有拿到平级奖励
                    hasSame = false;
                }

                LambdaQueryWrapper<TWallets> walletQuery = new LambdaQueryWrapper<>();
                walletQuery.in(TWallets::getCustomerId, walkInviterIds);
                List<TWallets> walletList = tWalletMapper.selectList(walletQuery);
                Map<Long, TWallets> walletsMap = walletList.stream().collect(Collectors.toMap(TWallets::getCustomerId, Function.identity()));

                List<TWallets> updateWalletList = walletList.stream().map(w->{
                    TWallets update = TWallets.builder()
                            .customerId(w.getCustomerId())
                            .build();

                    ReturnAwardVO custInviteAwardVO = inviteAward.get(w.getCustomerId());
                    BigDecimal custInviteAward = custInviteAwardVO==null?BigDecimal.ZERO:custInviteAwardVO.getReturnAwardAmt();

                    ReturnAwardVO custTeamAwardVO = teamAward.get(w.getCustomerId());
                    BigDecimal custTeamAward = custTeamAwardVO==null?BigDecimal.ZERO:custTeamAwardVO.getReturnAwardAmt();

                    BigDecimal award = custInviteAward.add(custTeamAward);

                    // 认购包收益奖励和团队激励都是USDO
                    BigDecimal bal = w.getUsdo().add(award);
                    update.setUsdo(bal);
                    return update;
                }).toList();

                itWalletService.updateBatchById(updateWalletList);

                List<TMembers> memberUpdateList = memberList.stream().map(m->{
                    TMembers updateMember = TMembers.builder()
                            .customerId(m.getCustomerId())
                            .build();

                    ReturnAwardVO custInviteAwardVO = inviteAward.get(m.getCustomerId());
                    BigDecimal custInviteAward = custInviteAwardVO==null?BigDecimal.ZERO:custInviteAwardVO.getReturnAwardAmt();

                    ReturnAwardVO custTeamAwardVO = teamAward.get(m.getCustomerId());
                    BigDecimal custTeamAward = custTeamAwardVO==null?BigDecimal.ZERO:custTeamAwardVO.getReturnAwardAmt();

                    updateMember.setAward(m.getAward().add(custInviteAward));
                    updateMember.setTeamAward(m.getTeamAward().add(custTeamAward));

                    return updateMember;
                }).toList();

                itMemberService.updateBatchById(memberUpdateList);

                List<TWalletJournal> inviteAwardJournalList = inviteAward.entrySet().stream().map(ia->{
                    TWallets wallet = walletsMap.get(ia.getKey());
                    BigDecimal beforeBal = wallet.getUsdo();
                    ReturnAwardVO custInviteAwardVO = inviteAward.get(ia.getKey());
                    BigDecimal amt = custInviteAwardVO==null?BigDecimal.ZERO:custInviteAwardVO.getReturnAwardAmt();

                    BigDecimal returnAmt = custInviteAwardVO==null?BigDecimal.ZERO:custInviteAwardVO.getReturnAmt();
                    returnAmt = returnAmt==null?BigDecimal.ZERO:returnAmt;
                    BigDecimal rate = custInviteAwardVO==null?BigDecimal.ZERO:custInviteAwardVO.getRate().multiply(CommonConstants.HUNDRED);

                    BigDecimal afterBal = beforeBal.add(amt);
                    TWalletJournal tWalletJournal = TWalletJournal.builder()
                            .customerId(wallet.getCustomerId())
                            .journalType(JournalTypeEnum.INVITE_AWARD.getCode())
                            .beforeBalance(beforeBal)
                            .amount(amt)
                            .afterBalance(afterBal)
                            .charges(BigDecimal.ZERO)
                            .direction(DirectionEnum.DEBIT.getCode())
                            .journalState(JournalStateEnum.FINISHED.getCode())
                            .currency(currency)
                            .remark(String.format("推荐奖励,来自[%s]的[%s]的[%s]%%",customerId, returnAmt, rate))
                            .build();
                    return tWalletJournal;
                }).toList();

                itWalletJournalService.saveBatch(inviteAwardJournalList);

                List<TWalletJournal> teamAwardJournalList = teamAward.entrySet().stream().map(ia->{
                    TWallets wallet = walletsMap.get(ia.getKey());
                    BigDecimal beforeBal = wallet.getUsdo();
                    ReturnAwardVO custTeamAwardVO = teamAward.get(ia.getKey());
                    BigDecimal amt = custTeamAwardVO==null?BigDecimal.ZERO:custTeamAwardVO.getReturnAwardAmt();

                    BigDecimal returnAmt = custTeamAwardVO==null?BigDecimal.ZERO:custTeamAwardVO.getReturnAmt();
                    returnAmt = returnAmt==null?BigDecimal.ZERO:returnAmt;
                    BigDecimal rate = custTeamAwardVO==null?BigDecimal.ZERO:custTeamAwardVO.getRate().multiply(CommonConstants.HUNDRED);

                    BigDecimal afterBal = beforeBal.add(amt);
                    TWalletJournal tWalletJournal = TWalletJournal.builder()
                            .customerId(wallet.getCustomerId())
                            .journalType(JournalTypeEnum.TEAM_AWARD.getCode())
                            .beforeBalance(beforeBal)
                            .amount(amt)
                            .afterBalance(afterBal)
                            .charges(BigDecimal.ZERO)
                            .direction(DirectionEnum.DEBIT.getCode())
                            .journalState(JournalStateEnum.FINISHED.getCode())
                            .currency(currency)
                            .remark(String.format("团队激励,来自[%s]的[%s]的[%s]%%",customerId, returnAmt, rate))
                            .build();
                    return tWalletJournal;
                }).toList();

                itWalletJournalService.saveBatch(teamAwardJournalList);
            }
        });
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void specialSubscribeAward(){
        List<TSubscribeOrderItems> unawardList = tSubscribeOrderItemMapper.findUnawardSpecial();
        if(CollectionUtils.isEmpty(unawardList)){
            log.warn("无可奖励的特殊认购单");
            return;
        }

        List<Long> unawardOrderIdList = unawardList.stream().map(TSubscribeOrderItems::getOrderId).toList();
        LambdaQueryWrapper<TOrders> orderQuery = new LambdaQueryWrapper<>();
        orderQuery.eq(TOrders::getOrderType, OrderTypeEnum.SUBSCRIBE.getCode());
        orderQuery.eq(TOrders::getPaymentState, PaymentStateEnum.FINISHED.getCode());
        orderQuery.eq(TOrders::getState, StateEnum.NORMAL.getCode());
        orderQuery.in(TOrders::getId, unawardOrderIdList);
        List<TOrders> orderList = tOrderMapper.selectList(orderQuery);
        Set<Long> orderCustomerIdSet = orderList.stream().map(TOrders::getCustomerId).collect(Collectors.toSet());
        List<TCustomers> customerList = tCustomerMapper.selectBatchIds(orderCustomerIdSet);
        if(CollectionUtils.isEmpty(customerList)) {
            log.warn("特殊认购单中无可奖励的客户");
            return;
        }
        List<TCustomers> normalCustomerList = customerList.stream().filter(c->StateEnum.isNormal(c.getState())).toList();
        if(CollectionUtils.isEmpty(normalCustomerList)) {
            log.warn("特殊认购单中无可奖励的正常客户");
            return;
        }
        List<Long> normalCustomerIdList = normalCustomerList.stream().map(TCustomers::getId).toList();
        List<TOrders> normalOrderList = orderList.stream().filter(o->normalCustomerIdList.contains(o.getCustomerId())).toList();
        if(CollectionUtils.isEmpty(normalOrderList)) {
            log.warn("特殊认购单中无可奖励的正常客户");
            return;
        }
        List<Long> normalOrderIdList = normalOrderList.stream().map(TOrders::getId).toList();

        LambdaUpdateWrapper<TSubscribeOrderItems> updateItemWrapper = new LambdaUpdateWrapper<>();
        updateItemWrapper.set(TSubscribeOrderItems::getAwardHandleState, HandleStateEnum.HANDLING.getCode());
        updateItemWrapper.in(TSubscribeOrderItems::getOrderId, normalOrderIdList);
        updateItemWrapper.eq(TSubscribeOrderItems::getAwardHandleState, HandleStateEnum.UNHANDLED.getCode());
        updateItemWrapper.eq(TSubscribeOrderItems::getReturnHandleState, HandleStateEnum.HANDLING.getCode());
        int effect = tSubscribeOrderItemMapper.update(updateItemWrapper);
        if(effect<=0){
            log.warn("无可奖励的特殊认购单");
            return;
        }

        LambdaQueryWrapper<TSubscribeOrderItems> queryHanding = new LambdaQueryWrapper<>();
        queryHanding.eq(TSubscribeOrderItems::getAwardHandleState, HandleStateEnum.HANDLING.getCode());
        List<TSubscribeOrderItems> handlingList = tSubscribeOrderItemMapper.selectList(queryHanding);
        if(CollectionUtils.isEmpty(handlingList)){
            log.warn("没有在处理中的待奖励的特殊认购单");
            return;
        }

        List<Long> handlingIdList = handlingList.stream().map(TSubscribeOrderItems::getOrderId).toList();
        List<TOrders> handlingOrderList = tOrderMapper.selectBatchIds(handlingIdList);
        List<TSubscribe> subscribeList = tSubscribeMapper.selectList(new QueryWrapper<>());

        LambdaQueryWrapper<TWalletJournal> journalListQuery = new LambdaQueryWrapper<>();
        journalListQuery.in(TWalletJournal::getOrderId, handlingIdList);
        journalListQuery.eq(TWalletJournal::getJournalType, JournalTypeEnum.SUBSCRIBE_ORDER.getCode());
        journalListQuery.eq(TWalletJournal::getJournalState, JournalStateEnum.FINISHED.getCode());
        List<TWalletJournal> journalList = tWalletJournalMapper.selectList(journalListQuery);
        if(CollectionUtils.isEmpty(journalList)){
            log.warn("无新增可处理的正常客户的特殊认购单业绩流水");
            return;
        }

        Map<Long, TSubscribeOrderItems> unawardMap = handlingList.stream().collect(Collectors.toMap(TSubscribeOrderItems::getOrderId, Function.identity()));
        Map<String, TSubscribe> subscribeMap = subscribeList.stream().collect(Collectors.toMap(TSubscribe::getSubscribeName, Function.identity()));
        Map<Long, TWalletJournal> journalMap = journalList.stream().collect(Collectors.toMap(TWalletJournal::getOrderId, Function.identity()));
        handlingOrderList.forEach(order->{
            Long orderId = order.getId();
            TSubscribeOrderItems subscribeItem = unawardMap.get(orderId);
            TWalletJournal journal = journalMap.get(orderId);
            TSubscribe tSubscribe = subscribeMap.get(subscribeItem.getSubscribeName());
            //calSpecialSubscribeAward(order, journal, tSubscribe);

            Long customerId = journal.getCustomerId();
            LambdaQueryWrapper<TInvite> inviteQuery = new LambdaQueryWrapper<>();
            inviteQuery.eq(TInvite::getInviteeId, customerId);
            TInvite tInvite = tInviteMapper.selectOne(inviteQuery);
            if(tInvite==null){
                log.warn("客户[{}]未受到邀请", customerId);
                return;
            }

            String invitePath = tInvite.getPath();
            Long inviterId = tInvite.getInviterId();
            List<String> pathList = Arrays.asList(invitePath.split(","));
            // 注意,父级顺序是从左到右的,即第一个元素是直接推荐人
            List<Long> walkInviterIds = pathList.stream().map(Long::valueOf).toList();
            // log.debug("invitePath: {}, {}", invitePath, pathList);

            LambdaQueryWrapper<TMembers> memberQuery = new LambdaQueryWrapper<>();
            memberQuery.in(TMembers::getCustomerId, walkInviterIds);
            List<TMembers> memberList = tMemberMapper.selectList(memberQuery);

            // 计算特殊认购直推奖励
            String currency = CurrencyEnum.USDO.getCode();
            BigDecimal investAmt = journal.getAmount();
            Long directParentId = walkInviterIds.get(0);

            Map<String, SubscribeIncentiveVO> specSubscribe = InitialGlobalConfig.SPEC_SUBSCRIBE_RULE;

            // 计算特殊认购奖励
            Map<Long, ReturnAwardVO> subscribeAward = new HashMap<>();
            if(!SubscribeLevelEnum.isNormal(tSubscribe.getSubscribeLevel())){
                SubscribeIncentiveVO specIncentive = specSubscribe.get(tSubscribe.getSubscribeName());
                BigDecimal awardAmt = specIncentive.getInviteAwardRate().multiply(investAmt).setScale(CommonConstants.DEFAULT_SCALE, RoundingMode.HALF_UP);
                ReturnAwardVO vo = new ReturnAwardVO();
                vo.setReturnAwardAmt(awardAmt);
                vo.setReturnAmt(investAmt);
                vo.setRate(specIncentive.getInviteAwardRate());
                subscribeAward.put(directParentId, vo);
            }
            if(MapUtil.isEmpty(subscribeAward)){
                log.warn("无特殊认购奖励");
                return;
            }

            LambdaQueryWrapper<TWallets> walletQuery = new LambdaQueryWrapper<>();
            walletQuery.in(TWallets::getCustomerId, walkInviterIds);
            List<TWallets> walletList = tWalletMapper.selectList(walletQuery);
            Map<Long, TWallets> walletsMap = walletList.stream().collect(Collectors.toMap(TWallets::getCustomerId, Function.identity()));

            List<TWallets> updateWalletList = walletList.stream().map(w->{
                TWallets update = TWallets.builder()
                        .customerId(w.getCustomerId())
                        .build();

                ReturnAwardVO raVO = subscribeAward.get(w.getCustomerId());
                BigDecimal custSubscribeAward = raVO==null?BigDecimal.ZERO:raVO.getReturnAwardAmt();

                BigDecimal bal = w.getUsdo().add(custSubscribeAward);
                update.setUsdo(bal);
                return update;
            }).toList();

            itWalletService.updateBatchById(updateWalletList);

            List<TMembers> memberUpdateList = memberList.stream().map(m->{
                TMembers updateMember = TMembers.builder()
                        .customerId(m.getCustomerId())
                        .build();

                ReturnAwardVO raVO = subscribeAward.get(m.getCustomerId());
                BigDecimal custSubscribeAward = raVO==null?BigDecimal.ZERO:raVO.getReturnAwardAmt();

                // 特殊认购奖励只算个人的奖励,不算团队的奖励
                updateMember.setAward(m.getAward().add(custSubscribeAward));
                return updateMember;
            }).toList();

            itMemberService.updateBatchById(memberUpdateList);

            List<TWalletJournal> specialAwardJournalList = memberList.stream().map(m->{
                TWallets wallet = walletsMap.get(m.getCustomerId());
                BigDecimal beforeBal = wallet.getUsdo();
                ReturnAwardVO raVO = subscribeAward.get(m.getCustomerId());
                BigDecimal amt = raVO==null?BigDecimal.ZERO:raVO.getReturnAwardAmt();
                BigDecimal afterBal = beforeBal.add(amt);

                BigDecimal returnAmt = raVO==null?BigDecimal.ZERO:raVO.getReturnAmt();
                BigDecimal rate = raVO==null?BigDecimal.ZERO:raVO.getRate().multiply(CommonConstants.HUNDRED);

                TWalletJournal tWalletJournal = TWalletJournal.builder()
                        .customerId(wallet.getCustomerId())
                        .orderId(orderId)
                        .journalType(JournalTypeEnum.SUBSCRIBE_AWARD.getCode())
                        .beforeBalance(beforeBal)
                        .amount(amt)
                        .afterBalance(afterBal)
                        .charges(BigDecimal.ZERO)
                        .direction(DirectionEnum.DEBIT.getCode())
                        .journalState(JournalStateEnum.FINISHED.getCode())
                        .currency(currency)
                        .remark(String.format("特殊认购包直推奖励,来自[%s]的[%s]的[%s]%%",customerId, returnAmt, rate))
                        .build();
                return tWalletJournal;
            }).toList();

            itWalletJournalService.saveBatch(specialAwardJournalList);

            TSubscribeOrderItems updateItem = TSubscribeOrderItems.builder()
                    .id(subscribeItem.getId())
                    .awardHandleState(HandleStateEnum.HANDLED.getCode())
                    .build();
            tSubscribeOrderItemMapper.updateById(updateItem);
        });
    }
}
